import java.util.ArrayList;


public class SymbolTable {

	public SymbolTableHeader header = null;
	public ArrayList<SymbolTableEntry> entries = null;

	public SymbolTable() {
		super();
	}

	public SymbolTable(SymbolTableHeader header) {
		this();
		this.setHeader(header);
	}

	public SymbolTable(Manager manager, SymbolTable backward) {
		this();
		this.setHeader(new SymbolTableHeader(manager, backward));
	}

	public SymbolTable(SymbolTableHeader header, ArrayList<SymbolTableEntry> entries) {
		this(header);
		this.setEntries(entries);
	}

	public SymbolTableHeader getHeader() {
		return this.header;
	}

	public ArrayList<SymbolTableEntry> getEntries() {
		return this.entries;
	}

	public void setHeader(SymbolTableHeader header) {
		if(header != null)
			this.header = header;
	}

	public void setEntries(ArrayList<SymbolTableEntry> entries) {
		if(entries != null && entries.size() > 0)
			this.entries = entries;
	}
	
	public void addEntry(String name, SymbolTable forward) {
		if(name != null) {
			if(this.entries == null)
				this.entries = new ArrayList<SymbolTableEntry>();
			this.entries.add(new SymbolTableEntry(name, forward, this.header.getOffset()));
		}
	}

	public void addEntry(int datatype, String name, boolean parameters) {
		
		int size=0;
		//Datatype Integer
		if(datatype == 0)
			size = 4;
		//Datatype Double
		if(datatype == 1)
			size = 8;
		//Datatype Boolean
		if(datatype == 2)
			size = 1;
		
		if(name != null) {
			if(this.entries == null)
				this.entries = new ArrayList<SymbolTableEntry>();
			this.entries.add(new SymbolTableEntry(datatype, name, this.header.getOffset(), parameters));
			this.header.incrementTopEntryByValue(size);
		}
	}

	public void addEntry(String name, int value, boolean parameters) {
		if(name != null) {
			if(this.entries == null)
				this.entries = new ArrayList<SymbolTableEntry>();
			this.entries.add(new SymbolTableEntry(name, value, this.header.getOffset(), parameters));
			this.header.incrementTopEntryByValue(4);
		}
	}

	public void addEntry(String name, double value, boolean parameters) {
		if(name != null) {
			if(this.entries == null)
				this.entries = new ArrayList<SymbolTableEntry>();
			this.entries.add(new SymbolTableEntry(name, value, this.header.getOffset(), parameters));
			this.header.incrementTopEntryByValue(8);
		}
	}

	public void addEntry(String name, boolean value, boolean parameters) {
		if(name != null) {
			if(this.entries == null)
				this.entries = new ArrayList<SymbolTableEntry>();
			this.entries.add(new SymbolTableEntry(name, value, this.header.getOffset(), parameters));
			this.header.incrementTopEntryByValue(1);
		}
	}

	public void addEntry(int datatype, String name) {
		this.addEntry(datatype, name, false);
	}
	
	public void addEntry(String name, int value) {
		this.addEntry(name, value, false);
	}
	
	public void addEntry(String name, double value) {
		this.addEntry(name, value, false);
	}
	
	public void addEntry(String name, boolean value) {
		this.addEntry(name, value, false);
	}
	
	public SymbolTableEntry lookup(String name, boolean recursive) {
		SymbolTableEntry ret = null;
		if(this.entries != null && this.entries.size() > 0) {			
			for (int i = 0; ret == null && i < this.entries.size(); i++) {
				if(this.entries.get(i).getName().equals(name))
					ret = this.entries.get(i);
			}
		}
		if(ret != null)
			return ret;
		else
			if(recursive && this.header.getBackward() != null)
				return this.header.getBackward().lookup(name, recursive);
			else
				return null;
	}
	
	public void calculateWidth() {
		int width = 0;
		if(this.entries != null && this.entries.size() > 0) {
			for (int i = 0; i < this.entries.size(); i++) {
				width += this.entries.get(i).getWidth();
			}
		}
		this.header.setWidth(width);
	}

	public String getSymbolTableHTMLFormat() {
		String entry = "<div class=\"CSSTableGenerator\"><table border=\"1\"><tr><td>Table Name:  " + this + "</td></tr><tr><td><table border=\"1\" width=\"100%\">" + this.header.getSymbolTableHeaderHTMLFormat() + "</table></td></tr>";
		if(this.entries != null && this.entries.size() > 0) {
			entry += "<tr><td><table border=\"1\" width=\"100%\">";
			entry += "<tr><td>Var Name</td><td>Var Type</td><td>Var Value</td><td>Offset</td><td>Var Size</td><td>Next Table</td></tr>";
			for (int i = 0; i < this.entries.size(); i++) {
				entry += this.entries.get(i).getSymbolTableEntryHTMLFormat();
			}
			entry += "</table></td></tr>";
		}
		entry += "</table></div>";
		return entry;
	}

	public SymbolTable createNewSymbolTable(Manager manager, SymbolTable backward) {
		return new SymbolTable(new SymbolTableHeader(manager, backward));
	}
	
}
